// echo partial file, should not compile along

using System;
using System.Reflection;
using System.Reflection.Emit;
using System.Collections.Generic;
using HarmonyLib;
using Utils;
namespace GongfaEffect;
using GameData.Utilities;
public partial class GongfaEffect {
//! 这里主要演示如何处理最大内力增减，可以用_extraNeili，但不推荐用这个
//! 这里的方法是，正练增加春宵双方的内息紊乱，璇女方将内力送给非璇女方，逆练时大量增加璇女方的内息紊乱，但璇女方可以借此吸收内力。
    public static class XuanNvXinJue {
        public const short Defkey_XuanNvXinJue=47; // 目前这个方法并没有被暴露在defkey之外，因此只能如此使用。
        public static void Patch(RobustHarmonyInstance HarmonyInstance, string ModIdStr){
            HarmonyInstance.PatchAll(System.Reflection.MethodBase.GetCurrentMethod().ReflectedType);
        }
//! 这里跟冰清玉洁一样，我们需要选择合适的注入位置。比如FixedAction就很不错，这是针对每一个人的，太吾并不能幸免。
        public static MethodInfo AddElement_PregnantStates=typeof(GameData.Domains.Character.CharacterDomain).GetMethod("AddElement_PregnantStates",(BindingFlags)(-1));
        [HarmonyPrefix]
        [HarmonyPatch(typeof(GameData.Domains.Character.Character),"ComplementPeriAdvanceMonth_ExecuteFixedActions")]
        public static unsafe void Prefix(GameData.Common.DataContext context, GameData.Domains.Character.ParallelModifications.PeriAdvanceMonthFixedActionModification mod){
//! 为了保证性能，这里必须尽早把一些没用的东西筛出去
            if(mod.MakeLoveTargetList == null) return;
            GameData.Domains.Character.Character character = mod.Character;

            GameData.Domains.CombatSkill.CombatSkill cs;
            if(character.GetGender()==0){ // 这边是以妹子为主导的春宵
                if(GameData.Domains.DomainManager.CombatSkill.TryGetElement_CombatSkills(new GameData.Domains.CombatSkill.CombatSkillKey(character.GetId(), Defkey_XuanNvXinJue),out cs) && cs.GetDirection() > GameData.Domains.CombatSkill.CombatSkillDirection.None) {
                    bool changed=character.beautify(context); // 让我们继续发福利，春宵美容。
                    for(int i=0;i<mod.MakeLoveTargetList.Count;i++) {
                        var male=mod.MakeLoveTargetList[i].Item1;
                        if(male.GetGender()==0)continue;
                        if(changed)character.beautify(context); // 为了（作死）节约计算量，这里如果未发现changed，说明医美已经完成，不需要进一步修改容貌，故不应继续执行函数。
                        if(mod.MakeLoveTargetList[i].Item2!=GameData.Domains.Character.ParallelModifications.PeriAdvanceMonthFixedActionModification.MakeLoveState.RapeFail){
                            ChangeNeili(character, male,(int)cs.GetDirection(),context);
                        }
                    }
                    if(changed)character.SetAvatar(character.GetAvatar(), context);
                }
            } else { // 这边是汉子主导的春宵
                for(int i=0;i<mod.MakeLoveTargetList.Count;i++) {
                    var female=mod.MakeLoveTargetList[i].Item1;
                    if(female.GetGender()==0 && GameData.Domains.DomainManager.CombatSkill.TryGetElement_CombatSkills(new GameData.Domains.CombatSkill.CombatSkillKey(female.GetId(), Defkey_XuanNvXinJue),out cs) && cs.GetDirection() > GameData.Domains.CombatSkill.CombatSkillDirection.None) {
                        if(female.beautify(context))female.SetAvatar(female.GetAvatar(), context); // 让我们继续发福利，春宵美容。
                        if(mod.MakeLoveTargetList[i].Item2!=GameData.Domains.Character.ParallelModifications.PeriAdvanceMonthFixedActionModification.MakeLoveState.RapeFail){
                            ChangeNeili(female, character,(int)cs.GetDirection(),context);
                        }
                    }
                }
            }
        }
        public static int TotalAmount=15;
        public static int DiscardAmount=10;
        public static void ChangeNeili(GameData.Domains.Character.Character female, GameData.Domains.Character.Character male,int direction, GameData.Common.DataContext context){
            var qi=female.GetDisorderOfQi();
            short femaleDelta=0;
            int addamount;
            if(direction==0){
                addamount=DecNeili(female, context, TotalAmount)-DiscardAmount;
                if(addamount>0) {
                    var disorder=(short)(500*addamount/(TotalAmount-DiscardAmount));
                    AddNeili(male, context, addamount);
                    femaleDelta=disorder;
                    male.ChangeDisorderOfQi(context, disorder);
                }
            } else {
                addamount=DecNeili(male, context, TotalAmount)-DiscardAmount;
                if(addamount>0){
                    var disorder=(short)(500*addamount/(TotalAmount-DiscardAmount));
                    AddNeili(female, context, addamount);
                    femaleDelta=(short)(disorder*2);
                }
            }
            if(addamount>0){
                female.SetDisorderOfQi((short)Math.Min(qi+femaleDelta,qi+Math.Max((6000-qi)/5,0)),context);
                Younger(male);
                Younger(female);
            } else if(context.Random.CheckPercentProb((DiscardAmount-addamount)*100/DiscardAmount)){
                Younger(male);
                Younger(female);
            }
        }
        public static int AddNeili(GameData.Domains.Character.Character character, GameData.Common.DataContext context, int AddAmount){
            Dictionary<short, GameData.Domains.CombatSkill.CombatSkill> combatSkills = GameData.Domains.DomainManager.CombatSkill.GetCharCombatSkills(character.GetId());
            bool haveSkillNeili=true;
            int repeat=AddAmount;
            while(haveSkillNeili){
                haveSkillNeili=false;
                foreach (KeyValuePair<short, GameData.Domains.CombatSkill.CombatSkill> keyValuePair in combatSkills) {
                    short skillTemplateId=keyValuePair.Key;
                    GameData.Domains.CombatSkill.CombatSkill skill=keyValuePair.Value;
                    if(skill.GetObtainedNeili()<skill.GetTotalObtainableNeili()){
                        skill.ObtainNeili(context,(short)1);
                        if(--repeat==0)break;
                        haveSkillNeili=true;
                    }
                }
            }
            return repeat;
        }
        public static int DecNeili(GameData.Domains.Character.Character character, GameData.Common.DataContext context, int DecAmount){
            Dictionary<short, GameData.Domains.CombatSkill.CombatSkill> combatSkills = GameData.Domains.DomainManager.CombatSkill.GetCharCombatSkills(character.GetId());
            bool haveSkillNeili=true;
            int repeat=DecAmount;
            while(haveSkillNeili){
                haveSkillNeili=false;
                foreach (KeyValuePair<short, GameData.Domains.CombatSkill.CombatSkill> keyValuePair in combatSkills) {
                    short skillTemplateId=keyValuePair.Key;
                    GameData.Domains.CombatSkill.CombatSkill skill=keyValuePair.Value;
                    if(skill.GetObtainedNeili()>0){
                        skill.ObtainNeili(context,(short)-1);
                        if(--repeat==0)break;
                        haveSkillNeili=true;
                    }
                }
            }
            return repeat;
        }
        public static FieldInfo _birthMonth=typeof(GameData.Domains.Character.Character).GetField("_birthMonth",(BindingFlags)(-1));
        public static FieldInfo _actualAge=typeof(GameData.Domains.Character.Character).GetField("_actualAge",(BindingFlags)(-1));
        public static FieldInfo _currAge=typeof(GameData.Domains.Character.Character).GetField("_currAge",(BindingFlags)(-1));
        public static void Younger(GameData.Domains.Character.Character character) {
            if(character.GetBirthMonth()==GameData.Domains.DomainManager.World.GetCurrDate()){
                if(character.GetCurrAge()>16){
                    _actualAge.SetValue(character,(short)(character.GetActualAge()-1));
                    _currAge.SetValue(character,(short)(character.GetCurrAge()-1));
                } else {
                    return;
                }
            }
            _birthMonth.SetValue(character,(sbyte)((character.GetBirthMonth()+1)%12));
        }
    }
}
